package edu.cmu.vlis.datamining.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jgrapht.graph.Multigraph;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;

import edu.cmu.vlis.datamining.core.Edge;
import edu.cmu.vlis.datamining.core.Vertex;

public class TestGraphParser {

    Map <String,Vertex> trgGraphVertexMap;
    Set<NodePair> nodePairs;
    BufferedReader reader;
    DocumentBuilder builder;
    Document doc;
    int badBlogsCount = 0;
    Multigraph<Vertex, Edge> trgGraph;
    private Set<Vertex> allVertices;

    public TestGraphParser(Map<String,Vertex> trgGraphMap, Multigraph<Vertex, Edge> trgGraph) {

        this.trgGraphVertexMap = trgGraphMap;
        this.nodePairs = new HashSet<NodePair>();
        this.allVertices = new HashSet<Vertex>();
        this.trgGraph = trgGraph;
        //Create a document Parser
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); 
        try {
            this.builder = domFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }

    }

    public void processBlog(String xmlBlog){

        //System.out.println("Starting processing of: "+vertexMap.size());
        try {
            InputSource inStream = new InputSource();
            inStream.setEncoding("UTF-8");
            inStream.setCharacterStream(new StringReader(xmlBlog));
            this.doc = this.builder.parse(inStream);
        }
        catch (MalformedByteSequenceException im) {
            System.err.println("MalformedByteSequenceException");
            badBlogsCount++;
            return;
        }catch (SAXException e) {
            System.err.println("SAXException");
            badBlogsCount++;
            return;
        } catch(IOException e){
            System.err.println("IOException");
            badBlogsCount++;
            return;
        }
        this.doc.getDocumentElement().normalize();

        //Retrieve Blog Url
        String blogUrl = doc.getElementsByTagName("weblog_url").item(0).getChildNodes().item(0).getNodeValue().trim();

        Vertex v = trgGraphVertexMap.get(blogUrl);
        NodeList outlinks = doc.getElementsByTagName("outlink");        

        if (v == null || (outlinks.getLength() == 0))
            return;

        Vertex vOut;
        for(int i=0;i<outlinks.getLength();i++) {
            Node outLinkNode = outlinks.item(i);
            if(outLinkNode.getNodeType() == Node.ELEMENT_NODE){
                String outSite =  ((Element)outLinkNode).getElementsByTagName("site").item(0).getChildNodes().item(0).getNodeValue().trim();

                if(!((vOut = this.trgGraphVertexMap.get(outSite)) ==  null) && !vOut.equals(v)){	
                    this.allVertices.add(v);
                    this.allVertices.add(vOut);
                    if(!this.trgGraph.containsEdge(v,vOut))
                        this.nodePairs.add( new NodePair(v,vOut));                    
                } 
            }
        }
    }
    
    public Set<Vertex> getVerticesToItr(){
    
	    return this.allVertices;
    }
    
    public void processGzippedFile(File file) {
        try {
            this.reader = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(file))));
            String line;
            boolean flag_on=false;
            String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
            String xmlBlog = xmlHeader;
            while ((line = reader.readLine()) != null) {
                if (line.contains("<post>")) {  //start building the message
                    flag_on = true;
                }
                if(flag_on)
                    xmlBlog = xmlBlog.concat(line);
                if(line.contains("</post>")) {
                    //process the XMl message as it is one blog
                    processBlog(xmlBlog);
                    xmlBlog = xmlHeader;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }

    public Set<NodePair> getNewEdges(File dir) {

        //Read the files in directory data
        File[] gzippedFiles = dir.listFiles();
        for(File gzippedFile : gzippedFiles){

            System.out.println("Starting processing of "+gzippedFile.getAbsolutePath());
            this.processGzippedFile(gzippedFile);
        }
        System.out.println("Done processing all gzipped files.");
        System.out.println("New Edges found : "+this.nodePairs.size());

        return this.nodePairs;
    }
}
